/*
 *  MidiParserTester.cpp
 *  Common UnitTest
 *
 *  Created by jiro on 12/04/02.
 *  Copyright 2012 jiro music. All rights reserved.
 *
 */

#include "MidiParserTester.h"

#include "../../Common/MidiSystem.h"
#include "../../Common/DebugSystem.h"

namespace sc
{
	void MidiParserTester::TestAll()
	{
		Test_ParseWithOptionOne000();
		Test_ParseWithOptionOne001();
		Test_ParseWithOptionOne002();
		Test_ParseWithOptionOne003();
		Test_ParseWithOptionOne004();
		Test_ParseWithOptionOne005();
	}


	void MidiParserTester::Test_ParseWithOptionOne000()
	{
		//	C4
		uint8_t bytes[] = { 0x9, 0x90, 0x3c, 0x60, 0x9, 0x90, 0x3c, 0x0 };

		bool res;
		const MidiMessage* msg;
		MidiParser parser( MidiParser::Option_One );
		std::queue< const MidiMessage* > messages; 
		res = parser.Parse( bytes, sizeof( bytes ) / sizeof( uint8_t ), messages );

		AssertEqual( res, true );
		AssertEqual( messages.size(), 2 );
		
		msg = messages.front();
		AssertEqual( msg->GetType(), MidiMessage::Type_NoteOn );
		messages.pop();

		AssertEqual( msg->Get1stDataByte(), MidiNote::C4 )
		AssertEqual( msg->Get2ndDataByte(), (uint8_t) 0x60 );

		msg = messages.front();
		AssertEqual( msg->GetType(), MidiMessage::Type_NoteOn );
		messages.pop();

		AssertEqual( msg->Get1stDataByte(), MidiNote::C4 )
		AssertEqual( msg->Get2ndDataByte(), (uint8_t) 0x0 );
	}

	void MidiParserTester::Test_ParseWithOptionOne001()
	{
		//	center C4 to C5 chromatic
		uint8_t bytes[] = { 0x9, 0x90, 0x3c, 0x29, 0x9, 0x90, 0x3c, 0x0, 
							0x9, 0x90, 0x3d, 0x44, 0x9, 0x90, 0x3d, 0x0, 
							0x9, 0x90, 0x3e, 0x4f, 0x9, 0x90, 0x3e, 0x0,
							0x9, 0x90, 0x3f, 0x52, 0x9, 0x90, 0x3f, 0x0, 
							0x9, 0x90, 0x40, 0x4f, 0x9, 0x90, 0x40, 0x0,
							0x9, 0x90, 0x41, 0x47, 0x9, 0x90, 0x41, 0x0, 
							0x9, 0x90, 0x42, 0x4c, 0x9, 0x90, 0x42, 0x0,
							0x9, 0x90, 0x43, 0x45, 0x9, 0x90, 0x43, 0x0,
							0x9, 0x90, 0x44, 0x4d, 0x9, 0x90, 0x44, 0x0,
							0x9, 0x90, 0x45, 0x4d, 0x9, 0x90, 0x45, 0x0,
							0x9, 0x90, 0x46, 0x5c, 0x9, 0x90, 0x46, 0x0,
							0x9, 0x90, 0x47, 0x45, 0x9, 0x90, 0x47, 0x0,
							0x9, 0x90, 0x48, 0x52, 0x9, 0x90, 0x48, 0x0 };

		bool res;
		const MidiMessage* msg;
		MidiParser parser( MidiParser::Option_One );
		std::queue< const MidiMessage* > messages; 
		res = parser.Parse( bytes, sizeof( bytes ) / sizeof( uint8_t ), messages );

		AssertEqual( res, true );
		AssertEqual( messages.size(), 26 );
		for ( int i = 0; i < 13; i++ )
		{
			MidiNote::Number number = MidiNote::Number( MidiNote::C4 + i );

			msg = messages.front();
			messages.pop();

			AssertEqual( msg->GetType(), MidiMessage::Type_NoteOn );
			AssertEqual( msg->Get1stDataByte(), number );
			AssertNotEqual( msg->Get2ndDataByte(), 0x00 );

			msg = messages.front();
			messages.pop();
			
			AssertEqual( msg->GetType(), MidiMessage::Type_NoteOn );
			AssertEqual( msg->Get1stDataByte(), number );
			AssertEqual( msg->Get2ndDataByte(), 0x00 );
		}
	}
	
	void MidiParserTester::Test_ParseWithOptionOne002()
	{
		//	volume change
		uint8_t bytes[] = { 0xb, 0xb0, 0x7, 0x1, 0xb, 0xb0, 0x7, 0x2 };
		
		bool res;
		const MidiMessage* msg;
		MidiParser parser( MidiParser::Option_One );
		std::queue< const MidiMessage* > messages; 
		res = parser.Parse( bytes, sizeof( bytes ) / sizeof( uint8_t ), messages );

		AssertEqual( res, true );
		AssertEqual( messages.size(), 2 );

		msg = messages.front();
		messages.pop();

		AssertEqual( MidiMessage::Type_ControlChange, msg->GetType() );
		AssertEqual( msg->GetChannelId(), 0x00 );
		AssertEqual( msg->Get1stDataByte(), MidiMessage::ControlChangeType_ChannelVolume );
		AssertEqual( msg->Get2ndDataByte(), 0x01 );
		
		msg = messages.front();
		messages.pop();

		AssertEqual( MidiMessage::Type_ControlChange, msg->GetType() );
		AssertEqual( msg->GetChannelId(), 0x00 );
		AssertEqual( msg->Get1stDataByte(), MidiMessage::ControlChangeType_ChannelVolume );
		AssertEqual( msg->Get2ndDataByte(), 0x02 );

	}

	void MidiParserTester::Test_ParseWithOptionOne003()
	{
		//	pedal on/off
		bool res;
		const MidiMessage* msg;	
		uint8_t bytes[] = { 0xb, 0xb0, 0x40, 0x7f, 0xb, 0xb0, 0x40, 0x0 };
		std::queue< const MidiMessage* > messages;
		MidiParser parser( MidiParser::Option_One );

		res = parser.Parse( bytes, sizeof( bytes ) / sizeof( uint8_t ), messages );

		AssertEqual( res, true );
		AssertEqual( messages.size(), 2 );

		msg = messages.front();
		messages.pop();

		AssertEqual( MidiMessage::Type_ControlChange, msg->GetType() );
		AssertEqual( msg->GetChannelId(), 0x00 );
		AssertEqual( msg->Get1stDataByte(), MidiMessage::ControlChangeType_DamperPedalOnOff );
		AssertEqual( msg->Get2ndDataByte(), 0x7f );
		
		msg = messages.front();
		messages.pop();

		AssertEqual( MidiMessage::Type_ControlChange, msg->GetType() );
		AssertEqual( msg->GetChannelId(), 0x00 );
		AssertEqual( msg->Get1stDataByte(), MidiMessage::ControlChangeType_DamperPedalOnOff );
		AssertEqual( msg->Get2ndDataByte(), 0x00 );

	}
	
	void MidiParserTester::Test_ParseWithOptionOne004()
	{
		//	pitch bend
		bool res;
		const MidiMessage* msg;	
		uint8_t bytes[] = { 
			0xe, 0xe0, 0x0, 0x3f, 0xe, 0xe0, 0x0, 0x3e, 
			0xe, 0xe0, 0x0, 0x3d, };
		std::queue< const MidiMessage* > messages;
		MidiParser parser( MidiParser::Option_One );

		res = parser.Parse( bytes, sizeof( bytes ) / sizeof( uint8_t ), messages );

		AssertEqual( res, true );
		AssertEqual( messages.size(), 3 );

		msg = messages.front();
		messages.pop();

		AssertEqual( msg->GetType(), MidiMessage::Type_PitchBendChange );

		AssertEqual( msg->GetChannelId(), 0x00 );
		AssertEqual( msg->Get1stDataByte(), 0x00 );
		AssertEqual( msg->Get2ndDataByte(), 0x3f );

		msg = messages.front();
		messages.pop();

		AssertEqual( msg->GetType(), MidiMessage::Type_PitchBendChange );
		AssertEqual( msg->GetChannelId(), 0x00 );
		AssertEqual( msg->Get1stDataByte(), 0x00 );
		AssertEqual( msg->Get2ndDataByte(), 0x3e );

		msg = messages.front();
		messages.pop();

		AssertEqual( msg->GetType(), MidiMessage::Type_PitchBendChange );
		AssertEqual( msg->GetChannelId(), 0x00 );
		AssertEqual( msg->Get1stDataByte(), 0x00 );
		AssertEqual( msg->Get2ndDataByte(), 0x3d );
	}
	
	void MidiParserTester::Test_ParseWithOptionOne005()
	{
		bool res;
		const MidiMessage* msg;	
		uint8_t bytes[] = {
			0xb, 0xb0, 0x1, 0x2, 0xb, 0xb0, 0x1, 0x3, };
		std::queue< const MidiMessage* > messages;
		MidiParser parser( MidiParser::Option_One );

		res = parser.Parse( bytes, sizeof( bytes ) / sizeof( uint8_t ), messages );

		AssertEqual( res, true );
		AssertEqual( messages.size(), 2 );

		msg = messages.front();
		messages.pop();

		AssertEqual( msg->Get1stDataByte(), MidiMessage::ControlChangeType_ModulationWheelOrLever );
		AssertEqual( msg->GetType(), MidiMessage::Type_ControlChange );
		AssertEqual( msg->GetChannelId(), 0x00 );
		AssertEqual( msg->Get2ndDataByte(), 0x02 );

		msg = messages.front();
		messages.pop();

		AssertEqual( msg->Get1stDataByte(), MidiMessage::ControlChangeType_ModulationWheelOrLever );
		AssertEqual( msg->GetType(), MidiMessage::Type_ControlChange );
		AssertEqual( msg->GetChannelId(), 0x00 );
		AssertEqual( msg->Get2ndDataByte(), 0x03 );
	}
}
